Shader "FullScreen/Shadow"
{
    Properties
    {
        _ZNear ("ZNear", Float) = 0.1
        _ZFar ("ZFar", Float) = 5
        _HBottom ("HBottom", Float) = 0
        _HTop ("HTop", Float) = 5
        _ShadowBias ("ShadowBias", Range(0, 1)) = 0.2
    }

    HLSLINCLUDE

    #pragma vertex Vert

    #pragma target 4.5
    #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
    #pragma multi_compile SHADOW_LOW SHADOW_MEDIUM SHADOW_HIGH SHADOW_VERY_HIGH
    // #pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST

    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl"
    
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/NormalBuffer.hlsl"
    
    #define LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/PunctualLightCommon.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl"

    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl"
    // #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadowLoop.hlsl"
    #include "ShadowHDShadowLoop.hlsl"
    
    // #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl"
    // #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightEvaluation.hlsl"

    float _ZNear;
    float _ZFar;
    float _HBottom;
    float _HTop;
    float3 _BackplateShadowTint;  // xyz: ShadowTint
    uint   _BackplateShadowFilter;
    float _ShadowBias;

    // The PositionInputs struct allow you to retrieve a lot of useful information for your fullScreenShader:
    // struct PositionInputs
    // {
    //     float3 positionWS;  // World space position (could be camera-relative)
    //     float2 positionNDC; // Normalized screen coordinates within the viewport    : [0, 1) (with the half-pixel offset)
    //     uint2  positionSS;  // Screen space pixel coordinates                       : [0, NumPixels)
    //     uint2  tileCoord;   // Screen tile coordinates                              : [0, NumTiles)
    //     float  deviceDepth; // Depth from the depth buffer                          : [0, 1] (typically reversed)
    //     float  linearDepth; // View space Z coordinate                              : [Near, Far]
    // };

    // To sample custom buffers, you have access to these functions:
    // But be careful, on most platforms you can't sample to the bound color buffer. It means that you
    // can't use the SampleCustomColor when the pass color buffer is set to custom (and same for camera the buffer).
    // float4 SampleCustomColor(float2 uv);
    // float4 LoadCustomColor(uint2 pixelCoords);
    // float LoadCustomDepth(uint2 pixelCoords);
    // float SampleCustomDepth(float2 uv);

    // There are also a lot of utility function you can use inside Common.hlsl and Color.hlsl,
    // you can check them out in the source code of the core SRP package.

    float4 FullScreenPass(Varyings varyings) : SV_Target
    {
        UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
        float depth = LoadCameraDepth(varyings.positionCS.xy);
        PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
        float3 viewDirection = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
        float4 color = float4(0.0, 0.0, 0.0, 0.0);

        // Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
        if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING)
            color = float4(CustomPassLoadCameraColor(varyings.positionCS.xy, 0), 1);

        // Add your custom pass code here
        float fogDensity = (posInput.linearDepth - _ZNear) / (_ZFar - _ZNear);
        fogDensity = saturate(fogDensity);
        
        float fogHightDensity = (posInput.positionWS.y - _HTop) / (_HBottom - _HTop);
        fogHightDensity = saturate(fogHightDensity);

        NormalData normalData;
        DecodeFromNormalBuffer(posInput.positionSS, normalData);

        HDShadowContext shadowContext = InitShadowContext();

        // 直接光阴影
        // DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex];
        // float3 L = -light.forward;
        // float3 shadow = GetDirectionalShadowAttenuation(shadowContext,
        //                         posInput.positionSS, posInput.positionWS, normalData.normalWS,
        //                         light.shadowIndex, L);
        // shadow = saturate(dot(normalData.normalWS, L));
        
        // lighting.diffuse = float4(light.color, 1.0);
    
        // SHADOW_TYPE shadow = EvaluateShadow_Directional(lightLoopContext, posInput, light, builtinData, bsdfData.normalWS);
        // lighting.diffuse *= ComputeShadowColor(shadow, light.shadowTint, light.penumbraTint);


        // 模糊阴影
        // DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex];
        // float3 L = -light.forward;
        // float3 positionWS = posInput.positionWS;
        // positionWS += L * _ShadowBias;
        
        // float3 shadowValue = GetDirectionalShadowAttenuation(shadowContext,
        //                         posInput.positionSS, positionWS, normalData.normalWS,
        //                         light.shadowIndex, L);
        
        // LightLoopContext lightLoopContext;
        // lightLoopContext.shadowValue = shadowValue;
        // lightLoopContext.shadowContext = shadowContext;
        // lightLoopContext.sampleReflection = 0;
        // lightLoopContext.splineVisibility = shadowValue;
        // InitContactShadow(posInput, lightLoopContext);

        // BuiltinData builtinData;
        // SHADOW_TYPE shadow = EvaluateShadow_Directional(lightLoopContext, posInput, light, builtinData, 
        //                         normalData.normalWS);
        // float3 shadowColor = ComputeShadowColor(shadow, _BackplateShadowTint, 0.0);
        // float3 shadowColor = ComputeShadowColor(shadowValue, _BackplateShadowTint, 0.0);

        // 精准阴影
        // uint renderingLayers = GetMeshRenderingLightLayer(); 
        float3 shadow3;
        ShadowLoopMin(shadowContext, posInput, normalData.normalWS, 
                    LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA
                    , DEFAULT_LIGHT_LAYERS, shadow3);
        float3 shadow = dot(shadow3, float3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0));
        // float3 shadow = ComputeShadowColor(shadowValue, _BackplateShadowTint, 0.0);
        // shadow *= saturate(dot(normalData.normalWS, L));

        // 第三种方法
        // DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex];
        // SHADOW_TYPE shadow = EvaluateShadow_Directional(lightLoopContext, posInput, light, builtinData, GetNormalForShadowBias(bsdfData));
        // float NdotL  = dot(bsdfData.normalWS, L); // No microshadowing when facing away from light (use for thin transmission as well)
        // shadow *= NdotL >= 0.0 ? ComputeMicroShadowing(GetAmbientOcclusionForMicroShadowing(bsdfData), NdotL, _MicroShadowOpacity) : 1.0;
        // lightColor.rgb *= ComputeShadowColor(shadow, light.shadowTint, light.penumbraTint);

        // color.rgb = lerp(color.rgb, float4(1, 1, 1, 1), saturate(fogHightDensity + fogDensity));

        // Fade value allow you to increase the strength of the effect while the camera gets closer to the custom pass volume
        float f = 1 - abs(_FadeValue * 2 - 1);
                
        // return float4(color.rgb + f, color.a);
        return float4(shadow, 1);
    }

    ENDHLSL

    SubShader
    {
        Tags{ "RenderPipeline" = "HDRenderPipeline" }
        Pass
        {
            Name "Custom Pass 0"

            ZWrite Off
            ZTest Always
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off

            HLSLPROGRAM
                #pragma fragment FullScreenPass
            ENDHLSL
        }
    }
    Fallback Off
}
